package com.iisigroup.http.test;


import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.UnrecoverableKeyException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;

import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLEngine;
import javax.net.ssl.SSLException;
import javax.net.ssl.SSLSession;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;
import javax.net.ssl.X509TrustManager;

import org.apache.commons.io.IOUtils; 
import org.apache.http.HttpEntity;
import org.apache.http.NameValuePair;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost; 
import org.apache.http.conn.ssl.SSLConnectionSocketFactory; 
import org.apache.http.conn.ssl.X509HostnameVerifier;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;

import com.iisigroup.http.test.RlAccount.Account; 
/**
 * Hello world!
 * 參考https://hc.apache.org/httpcomponents-client-4.3.x/quickstart.html
 * 而做出來的測試程式碼
 */
public class App3 {

	public static void main(String[] args) throws Exception {
//		while (true) {
//			new App3().testMethod();
//		}
		new App3().multiProcess();
	}
	private List<String> getAllPage(final String prefix){
	    return new Page().getAllPages(prefix);
	}
	public void testMethod() throws ClientProtocolException, IOException{	    	
	    	final CloseableHttpClient httpclient = getHttpClient();
	    	final HttpGet httpGet = new HttpGet("https://140.92.86.151:8443/nidp/idff/sso?id=1&sid=1&option=credential&sid=1");	    	
	    	final CloseableHttpResponse response1 = httpclient.execute(httpGet);
		// The underlying HTTP connection is still held by the response object
		// to allow the response content to be streamed directly from the network socket.
		// In order to ensure correct deallocation of system resources
		// the user MUST call CloseableHttpResponse#close() from a finally clause.
		// Please note that if response content is not fully consumed the underlying
		// connection cannot be safely re-used and will be shut down and discarded
		// by the connection manager. 
		try {
		    HttpEntity entity1 = response1.getEntity();
		    // do something useful with the response body
		    // and ensure it is fully consumed
		    String content =EntityUtils.toString(entity1);
		    EntityUtils.consume(entity1);
		} finally {
		    response1.close();
		}
		///pages/j_spring_security_check
		//http://192.168.10.18:6280/rl/pages/j_spring_security_check
		//HttpPost httpPost = new HttpPost( "https://idpFL.ris.gov.tw:8443/nidp/app/login?sid=1");
		HttpPost httpPost = new HttpPost( "https://idpFL.ris.gov.tw:8443/nidp/app/login?sid=1");
		List <NameValuePair> nvps = new ArrayList <NameValuePair>();
		Account account = 	RlAccount.getRandomAccount();
		nvps.add(new BasicNameValuePair("Ecom_User_ID", account.getUser()));
		nvps.add(new BasicNameValuePair("Ecom_Password", account.getPasswd()));
//		nvps.add(new BasicNameValuePair("Ecom_User_ID", "RF1200123"));
//		nvps.add(new BasicNameValuePair("Ecom_Password", "RF1200123"));
		httpPost.setEntity(new UrlEncodedFormEntity(nvps));
		CloseableHttpResponse response2 = httpclient.execute(httpPost);

		try {
//		    System.out.println(response2.getStatusLine());
		    HttpEntity entity2 = response2.getEntity();
		    String content =EntityUtils.toString(entity2);
		    // do something useful with the response body
		    // and ensure it is fully consumed
		    EntityUtils.consume(entity2);
		} finally {
		    response2.close();
		}
		 
		
		//http://targethost/homepage
		//http://192.168.10.18:6280/rl/pages/common/login.jsp
		CloseableHttpResponse response03 = null;
		// The underlying HTTP connection is still held by the response object
		// to allow the response content to be streamed directly from the network socket.
		// In order to ensure correct deallocation of system resources
		// the user MUST call CloseableHttpResponse#close() from a finally clause.
		// Please note that if response content is not fully consumed the underlying
		// connection cannot be safely re-used and will be shut down and discarded
		// by the connection manager. 
		for (int c = 0; c < 60; c++) {
			//http://rlfl.ris.gov.tw/rl/faces/pages/func/rl00001/rl00001.xhtml
		    HttpGet httpGet03 = new HttpGet( "http://rlfl.ris.gov.tw/rl/faces/pages/func/rl03100/rl03100.xhtml");
			
//		    final HttpGet httpGet03 = new HttpGet(allPages.get(RandomUtils.nextInt(allPages.size())));		    
//			InputStream ins = null;
			try {
				response03 = httpclient.execute(httpGet03);
//				System.out.println(response03.getStatusLine());
				HttpEntity entity3 = response03.getEntity();

				InputStream ins = entity3.getContent();
				final List<String> lines = IOUtils.readLines(ins);
				for (String line : lines) {
					System.out.println(line);
				}
				String content =EntityUtils.toString(entity3);
				// do something useful with the response body
				// and ensure it is fully consumed
				EntityUtils.consume(entity3);
				
			} finally {
				if (response03 != null) {
					response03.close();
				}
			}
		}
		//如果要測試戶籍員的反應...則要把httpclient.close();註解掉,這樣才會使得stuck thread 不會消失
//		httpclient.close();
	}
	public void multiProcess(){
		List<Future<List<String>>> data =null;
		final List<HttpTask> tasks = new ArrayList<HttpTask>();
		for(int j=0 ;j<10000;++j){
			tasks.add(new HttpTask());
		}
//		ExecutorService service = Executors.newCachedThreadPool();
				ExecutorService service = Executors.newFixedThreadPool(250);
        
        try {
        	 data = service.invokeAll(tasks, 10000, TimeUnit.SECONDS);
        } catch (InterruptedException e) {
			e.printStackTrace();
		} finally {
            service.shutdown();
        }
        if(data != null && data.size() > 0){
        	for(Future<List<String>> futureUnit :data ){
        		try {
					futureUnit.get();
				} catch (Exception e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}	
        	}
        }
	}
	public class HttpTask implements Callable<List<String>> {

		@Override
		public List<String> call() throws Exception {
			testMethod();
			return null;
		}}

	public CloseableHttpClient getHttpClient() {
//		try {
//			final SSLContextBuilder builder = new SSLContextBuilder();
//			builder.loadTrustMaterial(null, new TrustSelfSignedStrategy());
//			SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(
//					builder.build());
//			CloseableHttpClient httpclient = HttpClients.custom()
//					.setSSLSocketFactory(sslsf).build();
//			return httpclient;
//		} catch (Exception e) {
//			// TODO Auto-generated catch block
//			e.printStackTrace();
//			return HttpClients.createDefault();
//		}
		try {			
			SSLConnectionSocketFactory sslsf = getSSLConnectionSocketFactory();
			CloseableHttpClient httpclient = HttpClients.custom()
					.setSSLSocketFactory(sslsf).build();
			return httpclient;
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			return HttpClients.createDefault();
		} 
	} 
	public SSLConnectionSocketFactory getSSLConnectionSocketFactory()
			throws KeyStoreException, NoSuchAlgorithmException,
			CertificateException, FileNotFoundException, IOException,
			UnrecoverableKeyException, KeyManagementException {
		TrustManager[] trustAllCerts = new TrustManager[]{
			    new X509TrustManager() {
			        public java.security.cert.X509Certificate[] getAcceptedIssuers() {
			            return null;
			        }
			        public void checkClientTrusted(
			            java.security.cert.X509Certificate[] certs, String authType) {
			        }
			        public void checkServerTrusted(
			            java.security.cert.X509Certificate[] certs, String authType) {
			        }
			    }
			};
		SSLContext sslContext = SSLContext.getInstance("SSL");
		sslContext.init(null, trustAllCerts, new java.security.SecureRandom());
		SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(
		        sslContext,new TrustingHostnameVerifier());
		return sslsf;
	}

	private static final class TrustingHostnameVerifier implements
			X509HostnameVerifier {
		public boolean verify(String hostname, SSLSession session) {
			return true;
		}

		@Override
		public void verify(String host, SSLSocket ssl) throws IOException {
			
			System.out.println("verify(String host, SSLSocket ssl) throws IOException");
		}

		@Override
		public void verify(String host, X509Certificate cert)
				throws SSLException {
			// TODO Auto-generated method stub
			System.out.println("verify(String host, X509Certificate cert)");
		}

		@Override
		public void verify(String host, String[] cns, String[] subjectAlts)
				throws SSLException {
			// TODO Auto-generated method stub
			System.out.println("verify(String host, String[] cns, String[] subjectAlts)");
		}
	}
	public SSLEngine getSSLEngine()
			throws KeyStoreException, NoSuchAlgorithmException,
			CertificateException, FileNotFoundException, IOException,
			UnrecoverableKeyException, KeyManagementException {
		// Create/initialize the SSLContext with key material

		final char[] passphrase = "passphrase".toCharArray();

		// First initialize the key and trust material.
		KeyStore ksKeys = KeyStore.getInstance("JKS");
		ksKeys.load(new FileInputStream("testKeys"), passphrase);
		KeyStore ksTrust = KeyStore.getInstance("JKS");
		ksKeys.load(new FileInputStream("testTrust"), passphrase);

		// KeyManager's decide which key material to use.
		final KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
		kmf.init(ksKeys, passphrase);

		// TrustManager's decide whether to allow connections.
		TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509");
		tmf.init(ksTrust);

		final SSLContext sslContext = SSLContext.getInstance("TLS");
		sslContext.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);

		// We're ready for the engine.
		final SSLEngine engine = sslContext.createSSLEngine();

		// Use as client
		engine.setUseClientMode(true);
		return engine;
	}
	
}
